feat(contradictions): advisory scanner for conflicting approved claims#405
feat(contradictions): advisory scanner for conflicting approved claims#405jsdevninja wants to merge 3 commits into
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
WalkthroughAdds an advisory ChangesContradiction Scan Feature
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant CLI as contradict_scan
participant Scanner as contradictions.scan
participant Finder as find_candidates
participant Store as KBStore
participant Proposals as propose_relation
User->>CLI: Run contradict-scan with options
CLI->>Scanner: Call scan
Scanner->>Finder: Find candidate pairs
Finder->>Store: Read claims and existing contradiction records
Finder-->>Scanner: Return scored candidates
Scanner->>Proposals: Create pending proposal when writes are enabled
Proposals-->>Scanner: Return proposal id or error
Scanner-->>CLI: Return result rows
CLI-->>User: Print candidates and proposal ids
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@CHANGELOG.md`:
- Line 16: Capitalize the word after the period in the changelog sentence so it
reads as a new sentence; update the text containing `--entity`, `--limit`, and
the following `scoring` phrase to start with an uppercase letter.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 66e8ef38-6b6c-401c-87d9-3049d7e67505
📒 Files selected for processing (4)
CHANGELOG.mdsrc/vouch/cli.pysrc/vouch/contradictions.pytests/test_contradictions.py
|
@plind-junior Would you review please? |
a673128 to
c6eeb5a
Compare
|
@plind-junior pleaes review |
c6eeb5a to
c9d6c9c
Compare
walk approved claims grouped by shared entity, flag same-topic pairs that disagree in polarity, and file a pending `contradicts` relation proposal per surviving pair via proposals.propose_relation. read-only and advisory: the scanner never sets ClaimStatus.CONTESTED, never writes a Relation, and never touches Claim.contradicts — those only land once a human runs `vouch approve` (or the pre-existing manual lifecycle.contradict). scoring/grouping lives in the new src/vouch/contradictions.py, not storage.py. `vouch contradict-scan` mirrors `vouch dedup`'s cli-only shape: --threshold, --entity, --limit, and --dry-run/--no-dry-run (default dry-run). a pair already cross-linked via Claim.contradicts, joined by an approved contradicts edge, or with a pending contradicts proposal is skipped so repeat scans don't duplicate proposals. closes vouchdev#314
c9d6c9c to
b85ab9b
Compare
|
@plind-junior Please review |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@CHANGELOG.md`:
- Around line 164-171: Move the vouch contradict-scan changelog entry from the
[1.3.0] section into [Unreleased], preserving its existing text and formatting.
In `@src/vouch/contradictions.py`:
- Line 25: Convert the prose in the comments at src/vouch/contradictions.py
lines 25-25, 128-130, and 183-184, and src/vouch/cli.py lines 243-244 and
262-262 to lowercase, preserving their wording and comment structure.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: d01bc0ad-79ec-49f5-bd6b-8ee8375e9ced
📒 Files selected for processing (4)
CHANGELOG.mdsrc/vouch/cli.pysrc/vouch/contradictions.pytests/test_contradictions.py
🚧 Files skipped from review as they are similar to previous changes (1)
- tests/test_contradictions.py
| - `vouch contradict-scan` — an offline scanner that groups approved claims | ||
| by shared entity and heuristically flags same-topic pairs that disagree | ||
| in polarity. `--dry-run` (default) only prints candidates; without it, | ||
| each surviving pair files a pending `contradicts` relation proposal via | ||
| `proposals.propose_relation` for a human `vouch approve` — the scanner | ||
| itself never writes a `Relation` or a `CONTESTED` status. `--threshold`, | ||
| `--entity`, and `--limit` tune the scan. scoring lives in the new | ||
| `src/vouch/contradictions.py`. (#314) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Move the changelog entry to the [Unreleased] section.
As per coding guidelines, when adding a user-visible feature, the changelog entry must be placed under [Unreleased]. Currently, it is placed under the [1.3.0] release section.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@CHANGELOG.md` around lines 164 - 171, Move the vouch contradict-scan
changelog entry from the [1.3.0] section into [Unreleased], preserving its
existing text and formatting.
Source: Coding guidelines
|
|
||
| DEFAULT_THRESHOLD = 0.3 | ||
|
|
||
| # No-longer-live assertions aren't worth flagging against. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Convert comment prose to lowercase.
Several code comments begin with uppercase letters. As per path instructions, keep prose lowercase in code comments and review notes.
src/vouch/contradictions.py#L25-L25: downcase the comment text.src/vouch/contradictions.py#L128-L130: downcase the comment text.src/vouch/contradictions.py#L183-L184: downcase the comment text.src/vouch/cli.py#L243-L244: downcase the comment text.src/vouch/cli.py#L262-L262: downcase the comment text.
📍 Affects 2 files
src/vouch/contradictions.py#L25-L25(this comment)src/vouch/contradictions.py#L128-L130src/vouch/contradictions.py#L183-L184src/vouch/cli.py#L243-L244src/vouch/cli.py#L262-L262
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/vouch/contradictions.py` at line 25, Convert the prose in the comments at
src/vouch/contradictions.py lines 25-25, 128-130, and 183-184, and
src/vouch/cli.py lines 243-244 and 262-262 to lowercase, preserving their
wording and comment structure.
Source: Path instructions
|
new commits were pushed after authorization. auto-merge is disarmed and the label removed — re-add the auto-merge label (or comment /auto-merge) to re-arm on the new head. |
closes #314
summary
src/vouch/contradictions.py: a read-only heuristic scanner that groups approved claims by sharedClaim.entitiesand flags same-topic pairs whose text disagrees in polarity (one asserts, the other negates) as candidate contradictions.vouch contradict-scan(cli-only, matching howvouch dedupships without a dedicatedkb.*method):--threshold,--entity,--limit,--dry-run/--no-dry-run(default dry-run).--dry-run, each surviving pair files exactly one pendingcontradictsrelation proposal viaproposals.propose_relation, visible inkb.list_pending/vouch pending.Claim.contradicts, already joined by an approvedcontradictsrelation edge, or already carrying a pendingcontradictsproposal is skipped, so repeat scans don't pile up duplicates.ClaimStatus.CONTESTED, never writes aRelation, and never touchesClaim.contradicts— all business logic lives incontradictions.py,storage.pyis untouched.design note (worth a second pair of eyes)
approving the resulting relation proposal currently lands a plain
Relation(relation=CONTRADICTS)edge — it does not flip both claims toCONTESTEDor cross-linkClaim.contradicts. that full symmetric transition still only happens via the pre-existing, deliberately-manuallifecycle.contradict(kb.contradict), whose own docstring says it intentionally bypasses the proposal queue and warns against refactoring it for stricter gating. i keptproposals.approve()untouched rather than special-casingrelation == "contradicts"there, since that's shared code for every relation kind and the issue's acceptance checklist only requires the proposal to land as aCONTRADICTSedge on approval, not the status flip. happy to wire that up instead if the intended reading of "the actual write still flows through lifecycle.contradict semantics on approval" was thatkb.approveitself should trigger the full transition.testing
tests/test_contradictions.py(15 tests): candidate scoring/grouping, entity/threshold/limit filters, inactive-claim exclusion, all three duplicate-skip paths (contradicts field / approved edge / pending proposal), dry-run writes nothing, non-dry-run files exactly one proposal per pair and never mutates claim status or writes a relation directly, repeat scans don't duplicate, and a full scan → propose → approve integration test landing aCONTRADICTSedge.vouch contradict-scanend-to-end against a scratch kb (dry-run,--no-dry-run, re-scan dedup,vouch approve) — matches the automated coverage.ruff check src testsclean.mypy src— same 3 pre-existing errors as main (sandbox.pyos.getuid/os.getgidon non-posix, missingjinja2stubs); none in the touched files.pytest tests/ -q --ignore=tests/embeddings— ran locally on windows. two files (test_http_server.py,test_http_server_mcp.py) hang in this sandbox because they bind a real loopback socket, unrelated to this diff, so i excluded them locally; everything else passed except 8 pre-existing windows-only failures (posixos.getuid, unprivileged symlinks,/vs\path assertions) untouched by this change.tests/test_contradictions.pyis green.test plan
vouch contradict-scanlists candidate pairs, writes nothing in--dry-run(default)--dry-run, each surviving pair produces exactly one pendingcontradictsproposal visible inkb.list_pendingCONTESTED, never writes aRelation, never touchesClaim.contradicts--threshold,--entity,--limit,--dry-run/--no-dry-runbehave as documentedsrc/vouch/contradictions.py,storage.pyunchangedkb.*mcp/jsonl method), per the issue's stated allowanceSummary by CodeRabbit
vouch contradict-scanto scan approved claims for likely same-entity contradictions, ranking candidate pairs by similarity and negation polarity.--dry-run(default) to preview candidates, or live mode to create pending contradiction relation proposals for later approval.--threshold, optional--entityscoping, and--limitto tune results.